package com.ddm.service.impl.vxImpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.ddm.entity.vxEntity.Exam;
import com.ddm.entity.vxEntity.Score;
import com.ddm.entity.vxEntity.Test;
import com.ddm.entity.vxEntity.User;
import com.ddm.mapper.ExamMapper;
import com.ddm.mapper.ScoreMapper;
import com.ddm.mapper.TestMapper;
import com.ddm.mapper.UserMapper;
import com.ddm.service.vxService.ContestRankService;
import com.ddm.vo.vxVo.ContestRankVO;
import com.ddm.vo.vxVo.ContestRankStatisticsVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 竞赛排行榜服务实现类
 */
@Service
@Slf4j
public class ContestRankImpl implements ContestRankService {
    
    @Autowired
    private ScoreMapper scoreMapper;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private ExamMapper examMapper;
    
    @Autowired
    private TestMapper testMapper;
    
    @Override
    public List<ContestRankVO> getContestRanking(Long examId, Integer limit) {
        log.info("获取竞赛排行榜，竞赛ID: {}, 限制数量: {}", examId, limit);
        
        // 1. 获取竞赛信息
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            log.warn("竞赛不存在，竞赛ID: {}", examId);
            return new ArrayList<>();
        }
        
        // 2. 查询该竞赛的所有成绩，按分数降序排列
        LambdaQueryWrapper<Score> scoreWrapper = new LambdaQueryWrapper<>();
        scoreWrapper.eq(Score::getExamId, examId)
                   .orderByDesc(Score::getTotalScores);
        List<Score> allScores = scoreMapper.selectList(scoreWrapper);
        
        // 3. 计算获奖等级（基于所有参与者）
        int totalParticipants = allScores.size();
        int firstPrizeCount = calculatePrizeCount(totalParticipants, exam.getFirstPrizeRatio());
        int secondPrizeCount = calculatePrizeCount(totalParticipants, exam.getSecondPrizeRatio());
        int thirdPrizeCount = calculatePrizeCount(totalParticipants, exam.getThirdPrizeRatio());
        
        // 4. 构建排行榜数据（只取前limit名）
        List<ContestRankVO> ranking = new ArrayList<>();
        int displayCount = Math.min(limit, allScores.size());
        
        for (int i = 0; i < displayCount; i++) {
            Score score = allScores.get(i);
            User user = userMapper.selectById(score.getUserId());
            
            // 获取用户的总答题时间
            LambdaQueryWrapper<Test> testWrapper = new LambdaQueryWrapper<>();
            testWrapper.eq(Test::getExamId, examId)
                      .eq(Test::getUserId, score.getUserId());
            List<Test> userTests = testMapper.selectList(testWrapper);
            int totalDuration = userTests.stream()
                    .mapToInt(Test::getAnswerTime)
                    .sum();
            
            ContestRankVO rankVO = new ContestRankVO();
            rankVO.setRank(i + 1);
            rankVO.setUserId(score.getUserId());
            rankVO.setScore(score.getTotalScores());
            rankVO.setExamId(examId);
            rankVO.setExamName(exam.getExamName());
            rankVO.setParticipantCount(totalParticipants); // 设置参与人数
            rankVO.setDuration(totalDuration); // 设置总答题时间（秒）
            
            // 设置获奖等级（使用优化版本）
            String prizeLevel = getPrizeLevelOptimized(i + 1, totalParticipants, 
                                                     exam.getFirstPrizeRatio(), exam.getSecondPrizeRatio(), exam.getThirdPrizeRatio());
            String prizeRatio = getPrizeRatioOptimized(i + 1, totalParticipants,
                                                     exam.getFirstPrizeRatio(), exam.getSecondPrizeRatio(), exam.getThirdPrizeRatio());
            rankVO.setPrizeLevel(prizeLevel);
            rankVO.setPrizeRatio(prizeRatio);
            
            if (user != null) {
                rankVO.setOriginalUserName(user.getUserName());
                rankVO.setUserName(user.getUserName()); // 原始用户名，脱敏在控制器层处理
                rankVO.setAvatar(user.getPhotoUrl());
            }
            
            ranking.add(rankVO);
        }
        
        return ranking;
    }
    
    /**
     * 计算获奖人数
     */
    private int calculatePrizeCount(int totalParticipants, BigDecimal ratio) {
        if (ratio == null || ratio.compareTo(BigDecimal.ZERO) <= 0) {
            return 0;
        }
        
        // 特殊处理：当参与人数很少时，确保至少有人能获奖
        if (totalParticipants <= 3) {
            // 如果只有1-3人参与，第1名获得一等奖
            if (totalParticipants == 1) {
                return 1;
            } else if (totalParticipants == 2) {
                // 2人参与：第1名一等奖，第2名二等奖
                return ratio.compareTo(BigDecimal.valueOf(0.5)) >= 0 ? 1 : 0;
            } else {
                // 3人参与：第1名一等奖，第2名二等奖，第3名三等奖
                if (ratio.compareTo(BigDecimal.valueOf(0.33)) >= 0) {
                    return 1;
                } else if (ratio.compareTo(BigDecimal.valueOf(0.66)) >= 0) {
                    return 2;
                } else {
                    return 3;
                }
            }
        }
        
        // 正常计算
        BigDecimal count = ratio.multiply(BigDecimal.valueOf(totalParticipants));
        int result = count.setScale(0, RoundingMode.HALF_UP).intValue();
        
        // 确保至少有人获奖（如果比例不为0）
        if (result == 0 && ratio.compareTo(BigDecimal.ZERO) > 0) {
            return 1;
        }
        
        return result;
    }
    
    /**
     * 获取获奖等级
     */
    private String getPrizeLevel(int rank, int firstPrizeCount, int secondPrizeCount, int thirdPrizeCount) {
        if (rank <= firstPrizeCount) {
            return "一等奖";
        } else if (rank <= firstPrizeCount + secondPrizeCount) {
            return "二等奖";
        } else if (rank <= firstPrizeCount + secondPrizeCount + thirdPrizeCount) {
            return "三等奖";
        } else {
            return "未获奖";
        }
    }
    
    /**
     * 获取获奖等级（优化版本，考虑小规模竞赛）
     */
    private String getPrizeLevelOptimized(int rank, int totalParticipants, BigDecimal firstRatio, BigDecimal secondRatio, BigDecimal thirdRatio) {
        // 特殊处理小规模竞赛
        if (totalParticipants == 1) {
            return "一等奖";
        } else if (totalParticipants == 2) {
            return rank == 1 ? "一等奖" : "二等奖";
        } else if (totalParticipants == 3) {
            if (rank == 1) return "一等奖";
            else if (rank == 2) return "二等奖";
            else return "三等奖";
        }
        
        // 正常计算
        int firstPrizeCount = calculatePrizeCount(totalParticipants, firstRatio);
        int secondPrizeCount = calculatePrizeCount(totalParticipants, secondRatio);
        int thirdPrizeCount = calculatePrizeCount(totalParticipants, thirdRatio);
        
        if (rank <= firstPrizeCount) {
            return "一等奖";
        } else if (rank <= firstPrizeCount + secondPrizeCount) {
            return "二等奖";
        } else if (rank <= firstPrizeCount + secondPrizeCount + thirdPrizeCount) {
            return "三等奖";
        } else {
            return "未获奖";
        }
    }
    
    /**
     * 获取获奖比例
     */
    private String getPrizeRatio(int rank, int firstPrizeCount, int secondPrizeCount, int thirdPrizeCount,
                                BigDecimal firstRatio, BigDecimal secondRatio, BigDecimal thirdRatio) {
        if (rank <= firstPrizeCount) {
            return firstRatio != null ? firstRatio.multiply(BigDecimal.valueOf(100)).toString() + "%" : "0%";
        } else if (rank <= firstPrizeCount + secondPrizeCount) {
            return secondRatio != null ? secondRatio.multiply(BigDecimal.valueOf(100)).toString() + "%" : "0%";
        } else if (rank <= firstPrizeCount + secondPrizeCount + thirdPrizeCount) {
            return thirdRatio != null ? thirdRatio.multiply(BigDecimal.valueOf(100)).toString() + "%" : "0%";
        } else {
            return "0%";
        }
    }
    
    /**
     * 获取获奖比例（优化版本，考虑小规模竞赛）
     */
    private String getPrizeRatioOptimized(int rank, int totalParticipants, BigDecimal firstRatio, BigDecimal secondRatio, BigDecimal thirdRatio) {
        // 特殊处理小规模竞赛
        if (totalParticipants == 1) {
            return "100%";
        } else if (totalParticipants == 2) {
            return rank == 1 ? "50%" : "50%";
        } else if (totalParticipants == 3) {
            if (rank == 1) return "33%";
            else if (rank == 2) return "33%";
            else return "33%";
        }
        
        // 正常计算
        int firstPrizeCount = calculatePrizeCount(totalParticipants, firstRatio);
        int secondPrizeCount = calculatePrizeCount(totalParticipants, secondRatio);
        int thirdPrizeCount = calculatePrizeCount(totalParticipants, thirdRatio);
        
        if (rank <= firstPrizeCount) {
            return firstRatio != null ? firstRatio.multiply(BigDecimal.valueOf(100)).toString() + "%" : "0%";
        } else if (rank <= firstPrizeCount + secondPrizeCount) {
            return secondRatio != null ? secondRatio.multiply(BigDecimal.valueOf(100)).toString() + "%" : "0%";
        } else if (rank <= firstPrizeCount + secondPrizeCount + thirdPrizeCount) {
            return thirdRatio != null ? thirdRatio.multiply(BigDecimal.valueOf(100)).toString() + "%" : "0%";
        } else {
            return "0%";
        }
    }
    
    @Override
    public ContestRankStatisticsVO getContestRankStatistics(Long examId) {
        log.info("获取竞赛排行榜统计信息，竞赛ID: {}", examId);
        
        // 1. 获取竞赛信息
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            log.warn("竞赛不存在，竞赛ID: {}", examId);
            return new ContestRankStatisticsVO();
        }
        
        // 2. 查询该竞赛的所有成绩
        LambdaQueryWrapper<Score> scoreWrapper = new LambdaQueryWrapper<>();
        scoreWrapper.eq(Score::getExamId, examId);
        List<Score> scores = scoreMapper.selectList(scoreWrapper);
        
        // 3. 计算统计信息
        ContestRankStatisticsVO statistics = new ContestRankStatisticsVO();
        statistics.setExamId(examId);
        statistics.setExamName(exam.getExamName());
        statistics.setParticipantCount(scores.size());
        statistics.setFullScore(100); // 假设满分为100，实际应该从竞赛配置中获取
        
        if (!scores.isEmpty()) {
            // 计算平均分
            double averageScore = scores.stream()
                    .mapToInt(Score::getTotalScores)
                    .average()
                    .orElse(0.0);
            statistics.setAverageScore(averageScore);
            
            // 计算最高分和最低分
            int maxScore = scores.stream()
                    .mapToInt(Score::getTotalScores)
                    .max()
                    .orElse(0);
            int minScore = scores.stream()
                    .mapToInt(Score::getTotalScores)
                    .min()
                    .orElse(0);
            statistics.setMaxScore(maxScore);
            statistics.setMinScore(minScore);
            
            // 计算及格人数（假设60分为及格线）
            long passCount = scores.stream()
                    .filter(score -> score.getTotalScores() >= 60)
                    .count();
            statistics.setPassCount((int) passCount);
            statistics.setPassRate(scores.size() > 0 ? (double) passCount / scores.size() : 0.0);
        } else {
            statistics.setAverageScore(0.0);
            statistics.setMaxScore(0);
            statistics.setMinScore(0);
            statistics.setPassCount(0);
            statistics.setPassRate(0.0);
        }
        
        return statistics;
    }
    
    @Override
    public ContestRankVO getMyContestRank(Long examId, Long userId) {
        log.info("获取指定用户的竞赛排名，竞赛ID: {}, 用户ID: {}", examId, userId);
        
        // 1. 获取竞赛信息
        Exam exam = examMapper.selectById(examId);
        if (exam == null) {
            log.warn("竞赛不存在，竞赛ID: {}", examId);
            return new ContestRankVO();
        }
        
        // 2. 查询该用户在该竞赛中的成绩
        LambdaQueryWrapper<Score> userScoreWrapper = new LambdaQueryWrapper<>();
        userScoreWrapper.eq(Score::getExamId, examId)
                       .eq(Score::getUserId, userId);
        Score userScore = scoreMapper.selectOne(userScoreWrapper);
        
        if (userScore == null) {
            log.warn("用户未参与该竞赛，用户ID: {}, 竞赛ID: {}", userId, examId);
            ContestRankVO rank = new ContestRankVO();
            rank.setExamId(examId);
            rank.setUserId(userId);
            rank.setRank(0);
            rank.setScore(0);
            rank.setExamName(exam.getExamName());
            
            // 获取参与人数
            LambdaQueryWrapper<Score> participantWrapper = new LambdaQueryWrapper<>();
            participantWrapper.eq(Score::getExamId, examId);
            int participantCount = scoreMapper.selectCount(participantWrapper);
            rank.setParticipantCount(participantCount);
            
            return rank;
        }
        
        // 3. 查询该竞赛的所有成绩，计算用户排名
        LambdaQueryWrapper<Score> allScoresWrapper = new LambdaQueryWrapper<>();
        allScoresWrapper.eq(Score::getExamId, examId)
                       .orderByDesc(Score::getTotalScores);
        List<Score> allScores = scoreMapper.selectList(allScoresWrapper);
        
        // 4. 计算用户排名
        int userRank = 1;
        for (Score score : allScores) {
            if (score.getUserId().equals(userId)) {
                break;
            }
            userRank++;
        }
        
        // 5. 获取用户信息
        User user = userMapper.selectById(userId);
        
        // 6. 计算获奖等级
        int totalParticipants = allScores.size();
        int firstPrizeCount = calculatePrizeCount(totalParticipants, exam.getFirstPrizeRatio());
        int secondPrizeCount = calculatePrizeCount(totalParticipants, exam.getSecondPrizeRatio());
        int thirdPrizeCount = calculatePrizeCount(totalParticipants, exam.getThirdPrizeRatio());
        
        // 7. 构建排名信息
        ContestRankVO rank = new ContestRankVO();
        rank.setRank(userRank);
        rank.setUserId(userId);
        rank.setScore(userScore.getTotalScores());
        rank.setExamId(examId);
        rank.setExamName(exam.getExamName());
        rank.setParticipantCount(totalParticipants); // 设置参与人数
        
        // 获取用户的总答题时间
        LambdaQueryWrapper<Test> testWrapper = new LambdaQueryWrapper<>();
        testWrapper.eq(Test::getExamId, examId)
                  .eq(Test::getUserId, userId);
        List<Test> userTests = testMapper.selectList(testWrapper);
        int totalDuration = userTests.stream()
                .mapToInt(Test::getAnswerTime)
                .sum();
        rank.setDuration(totalDuration); // 设置总答题时间（秒）
        
        // 设置获奖等级（使用优化版本）
        String prizeLevel = getPrizeLevelOptimized(userRank, totalParticipants, 
                                                 exam.getFirstPrizeRatio(), exam.getSecondPrizeRatio(), exam.getThirdPrizeRatio());
        String prizeRatio = getPrizeRatioOptimized(userRank, totalParticipants,
                                                 exam.getFirstPrizeRatio(), exam.getSecondPrizeRatio(), exam.getThirdPrizeRatio());
        rank.setPrizeLevel(prizeLevel);
        rank.setPrizeRatio(prizeRatio);
        
        if (user != null) {
            rank.setOriginalUserName(user.getUserName());
            rank.setUserName(user.getUserName()); // 原始用户名，脱敏在控制器层处理
            rank.setAvatar(user.getPhotoUrl());
        }
        
        return rank;
    }
    
    @Override
    public List<ContestRankVO> getOverallContestRanking(Integer limit) {
        log.info("获取综合竞赛排行榜，限制数量: {}", limit);
        
        // 1. 查询所有竞赛的成绩，按用户分组计算总分
        LambdaQueryWrapper<Score> scoreWrapper = new LambdaQueryWrapper<>();
        List<Score> allScores = scoreMapper.selectList(scoreWrapper);
        
        // 2. 按用户ID分组，计算每个用户的总分
        Map<Long, Integer> userTotalScores = allScores.stream()
                .collect(Collectors.groupingBy(
                        Score::getUserId,
                        Collectors.summingInt(Score::getTotalScores)
                ));
        
        // 3. 按总分排序，取前limit名
        List<Map.Entry<Long, Integer>> sortedUsers = userTotalScores.entrySet().stream()
                .sorted(Map.Entry.<Long, Integer>comparingByValue().reversed())
                .limit(limit)
                .collect(Collectors.toList());
        
        // 4. 构建综合排行榜
        List<ContestRankVO> ranking = new ArrayList<>();
        int totalParticipants = userTotalScores.size(); // 总参与人数
        
        for (int i = 0; i < sortedUsers.size(); i++) {
            Map.Entry<Long, Integer> entry = sortedUsers.get(i);
            Long userId = entry.getKey();
            Integer totalScore = entry.getValue();
            
            User user = userMapper.selectById(userId);
            
            ContestRankVO rankVO = new ContestRankVO();
            rankVO.setRank(i + 1);
            rankVO.setUserId(userId);
            rankVO.setScore(totalScore);
            rankVO.setExamId(null); // 综合排行榜不关联具体竞赛
            rankVO.setExamName("综合排行榜");
            rankVO.setParticipantCount(totalParticipants); // 设置总参与人数
            
            if (user != null) {
                rankVO.setOriginalUserName(user.getUserName());
                rankVO.setUserName(user.getUserName()); // 原始用户名，脱敏在控制器层处理
                rankVO.setAvatar(user.getPhotoUrl());
            }
            
            ranking.add(rankVO);
        }
        
        return ranking;
    }
} 